package com.puhui.lib.network

import com.puhui.lib.BuildConfig
import com.puhui.lib.http.retrofit.BaseServiceApi
import com.puhui.lib.network.callback.NetworkCallBack
import com.puhui.lib.network.interceptors.AndroidLogger
import com.puhui.lib.network.interceptors.HttpLoggingInterceptor
import io.reactivex.Observable
import io.reactivex.Observer
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import okhttp3.*
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
import java.io.File
import java.net.Proxy
import java.util.concurrent.TimeUnit

/**
 * 错误总结：
 * *   1、OkHttp报错javax.net.ssl.SSLHandshakeException: Handshake failed:  先确认下是否自己的手机或模拟器与服务器时间相同
 * *      https://blog.csdn.net/qq_32405269/article/details/78343112
 *
 * *   2、https://www.it610.com/article/1281673515799429120.htm
 * *      RxJava+Retrofit的一个bug,就是如果后台只返回一个响应码，而不返回body的情况下，
 * *      会出现java.lang.NullPointerException: Null is not a valid element的bug, 看了一下官网，好像是Rxjava2的onNext()需要返回一个body
 * *   3、如果后台将错误状态码与Http的状态码混合在一起处理, 那么可以从errorBody中取错误内容
 * *      val errorBody = t.response()?.errorBody();  val errorInfo = Gson().fromJson<BaseBean>(it.string(), BaseBean::class.java)
 */
object NetworkManager {

    private val mInterceptors: MutableList<Interceptor> = mutableListOf()

    private val mBaseApiMaps = mutableMapOf<Class<*>, BaseServiceApi>()
    private val mBaseUrlMaps = mutableMapOf<Class<*>, String>()

    /**
     * 在NetworkManager为lib或jar包的情况下, 提供给外部使用的api
     */
    fun addInterceptor(interceptor: Interceptor) {
        mInterceptors.add(interceptor)
    }

    fun <T : BaseServiceApi> addBaseUrl(api: Class<T>, baseUrl: String) {
        mBaseUrlMaps[api] = baseUrl
    }

    /**
     * 在NetworkManager为lib或jar包的情况下, 提供给外部使用的api
     */
    fun <T : BaseServiceApi> getApiService(api: Class<T>): T {
        val apiService = mBaseApiMaps[api]
        if (apiService is BaseServiceApi) {
            return apiService as T
        } else {
            val baseUrl = mBaseUrlMaps[api] ?: throw IllegalArgumentException("baseUrl must be initialled first")

            val retrofit = Retrofit.Builder()
                .baseUrl(baseUrl)
                .client(getOkHttpClient())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
//                        .addConverterFactory(StringCon)
                .build().create(api)
            mBaseApiMaps[api] = retrofit
            return retrofit
        }
    }

    private fun getOkHttpClient(): OkHttpClient {
        val timeOut = 20L
        val builder: OkHttpClient.Builder = OkHttpClient.Builder()
            .proxy(Proxy.NO_PROXY)
            .connectTimeout(timeOut, TimeUnit.SECONDS)
            .readTimeout(timeOut, TimeUnit.SECONDS)
            .writeTimeout(timeOut, TimeUnit.SECONDS)

//        //拦截请求地址和参数
//        val requestInterceptor = RequestInterceptor()
//        builder.addInterceptor(requestInterceptor)
        mInterceptors.forEach { interceptor ->
            builder.addInterceptor(interceptor)
        }

        //拦截返回结果，并打印
        if (BuildConfig.DEBUG) {
            val httpLogInterceptor = HttpLoggingInterceptor(AndroidLogger())
            httpLogInterceptor.level = HttpLoggingInterceptor.Level.BODY
            builder.addInterceptor(httpLogInterceptor)
        }

        return builder.build()
    }

    fun <T> doSubscribe(source: Observable<T>, callBack: NetworkCallBack<T>?) {
        source.subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
//            .compose(activity.bindUntilEvent(ActivityEvent.DESTROY))
            .subscribe(getObserver(callBack))
    }

    private fun <T> getObserver(callBack: NetworkCallBack<T>?): Observer<T> {

        return object : Observer<T> {
            override fun onSubscribe(d: Disposable) {
            }

            override fun onNext(t: T) {
                callBack?.apply {
                    onResponse(response = t)
                }
            }

            override fun onError(e: Throwable) {
                callBack?.apply {
                    onFailure(e)
                }
            }

            override fun onComplete() {
            }
        }
    }

    fun createPartFromFile(file: File): MultipartBody.Part {
        // MultipartBody.Part  和后端约定好Key，这里的partName是用image
        return MultipartBody.Part.createFormData(  //image/jpeg
            "image", file.name, RequestBody.create(MediaType.parse("multipart/form-data"), file)
        )
    }
}